﻿namespace IBTrader.Modules.Log
{
    using IBFutures.Modules.Log;
    using IBTrader.Model;
    using NLog;
    using System;
    using System.IO;
    using System.Runtime.Remoting.Messaging;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.ServiceModel.Web;
    using System.Text;
    using System.Windows.Forms;

    class WebHost
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private ServiceHost host;
        public WebHost(Store store, string port)
        {
            W.X(logger, () =>
            {
                string baseAddress = string.Format("http://{0}:{1}/", Environment.MachineName, port);
                host = new ServiceHost(new Service { store = store }, new Uri(baseAddress));
                host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
            });
        }
        public void Open(object _, EventArgs __)
        {
            W.Q(logger, () => host.Open());
        }
        public void Close(object _, EventArgs __)
        {
            W.X(logger, () => host.Close());
        }
        [ServiceContract] interface IService
        {
            [WebGet]
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginStatus(AsyncCallback callback, object asyncState);
            Stream EndStatus(IAsyncResult result);
        }
        [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] class Service : IService
        {
            internal Store store { get; set; }
            private Stream Status()
            {
                logger.Debug("webHost Get");
                var ms = new MemoryStream();

                W.X(logger, delegate()
                {
                    var sw = new StreamWriter(ms, Encoding.Unicode);
                    //if (IBLog.Offline) sw.WriteLine("===== OFFLINE =====");
                    //sw.WriteLine("AvailableMemory {0:n} Version {1} {2}", Memory.AvailableMemory, Application.ProductVersion, ApplicationInfo.UpdateArgs);

                    //Action<string, Func<Store.OrderRow, string>> group = (txt,func) => sw.Write(txt + 
                    //    string.Join(" ", store.Order.GroupBy(func).Select(g => string.Format(" {0} {1} ", g.Key, g.Count()))) + "\r\n");
                    //group("Order Type:", c => c.Type);
                    //group("Order Action:", c => c.Action);

                    foreach (var contract in store.Contracts)
                    {
                        //var orders = store.Order.Where(m => m.Filled > 0 && m.Contract == contract.Id).ToArray();
                        //var total = 0.0;
                        //for (int i = 0; i < orders.Length; i++)
                        //{
                        //    sw.Write(orders[i].ToString());
                        //    if (orders[i].Type != Order.OType.Enter.ToString())
                        //    {
                        //        var amount = (orders[i].FillPrice - orders[i - 1].FillPrice) * (orders[i - 1].Action == IB.OrderAction.BUY.ToString() ? 1 : -1);
                        //        total += amount;
                        //        sw.Write(" {0:0.00}", amount);
                        //    }
                        //    else if (i == orders.Length - 1)
                        //    {
                        //        var amount = (contract.Price - orders[i].FillPrice) * (orders[i].Action == IB.OrderAction.BUY.ToString() ? 1 : -1);
                        //        total += amount;
                        //        sw.Write(" {0:0.00}", amount);
                        //    }
                        //    sw.WriteLine();
                        //}
                        //sw.WriteLine("{0} [Total #{1} {2:0.00} ]", contract, orders.Count(), total);
                        sw.WriteLine(contract.Symbol);
                    }

                    //store.Log.ToList().ForEach(log => sw.WriteLine("{0} {1}", log.DateTime, log.Text));

                    sw.Flush();
                });

                ms.Position = 0;
                return ms;
            }
            public IAsyncResult BeginStatus(AsyncCallback callback, object asyncState)
            {
                Func<Stream> func = Status;
                return func.BeginInvoke(callback, asyncState);
            }
            public Stream EndStatus(IAsyncResult result)
            {
                Func<Stream> func = (Func<Stream>)((AsyncResult)result).AsyncDelegate;
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
                return func.EndInvoke(result);
            }
        }
    }
}